template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
network::socket<blocking_policy, locking_policy, error_policy>::socket()
:_sock(-1)
{
	locking_policy::lock();
	WSADATA wsa; 
	WSAStartup(MAKEWORD(2, 0), &wsa);

	/*
	 * Creation of the Socket
	 */
	if((_sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
		error_policy::msg("Failed to create a socket");
	}
	blocking_policy::set_blocking(_sock);

	locking_policy::unlock();
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
network::socket<blocking_policy, locking_policy, error_policy>::socket(
		const string &addr, int port)
:_sock(-1)
{
	locking_policy::lock();
	memset(&_serv, 0, sizeof(_serv));
	_serv.sin_family = AF_INET;
	_serv.sin_addr.s_addr = inet_addr(addr.c_str());
	_serv.sin_port = htons(port);

	/*
	 * Creation of the Socket
	 */
	if((_sock = ::socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
		error_policy::msg("Failed to create a socket");
	}

	/*
	 * Establish the connection
	 */
	if(connect(_sock, (SOCKADDR*) &_serv, sizeof(_serv)) == SOCKET_ERROR) {
		error_policy::msg("Failed to connect with the server");
	}
	blocking_policy::set_blocking(_sock);
	locking_policy::unlock();
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
network::socket<blocking_policy, locking_policy, error_policy>::~socket()
{
	locking_policy::lock();
	if(_sock != -1) {
		closesocket(_sock);
	}
	locking_policy::unlock();
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
string network::socket<blocking_policy, locking_policy, error_policy>::read() 
{
	locking_policy::lock();
	/*
	 * reading the whole networking-buffer
	 */
	int received;
	string ret_val;
	char buff[1024];
	if(_sock == -1) return "";

	received = recv(_sock, buff, 1024, 0);
	if(received == SOCKET_ERROR) {
		stringstream strm;
		strm << "Error in socket::recv: ";
		error_policy::msg(strm.str());
	}
	if(blocking_policy::is_lost(received)) {
		_sock = -1;
		error_policy::connection_lost();
	}
	ret_val.append(buff, received);

	locking_policy::unlock();
	return ret_val;
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
void network::socket<blocking_policy, locking_policy, error_policy>::write(
		const string &str) 
{
	locking_policy::lock();
	if(_sock == -1) return;
	if(send(_sock, str.c_str(), strlen((char*)str.c_str()), 0) == 
	   SOCKET_ERROR) {
		error_policy::msg("Error in socket::write");
	}
	locking_policy::unlock();
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
bool network::socket<blocking_policy, locking_policy, error_policy>::bind(
		int port)
{
	if(_sock == -1) {
		error_policy::msg("Error in socket::listen: _sock == -1");
	}

	locking_policy::lock();

	_serv.sin_family = AF_INET;
	_serv.sin_addr.s_addr = INADDR_ANY;
	_serv.sin_port = htons(port);

	bool rtrn =::bind(_sock, (SOCKADDR*)&_serv, sizeof(_serv)) != -1;
	locking_policy::unlock();

	return rtrn;
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
bool network::socket<blocking_policy, locking_policy, error_policy>::listen() 
	const
{
	if(_sock == -1) {
		error_policy::msg("Error in socket::listen: _sock == -1");
	}
	locking_policy::lock();
	bool rtrn = (::listen(_sock, MAXCONNECTIONS)) != -1;
	locking_policy::unlock();
	return rtrn;
}

template <
	class blocking_policy, 
	class locking_policy,
	class error_policy
>
template <
	class socket_rhs
>
bool network::socket<blocking_policy, locking_policy, error_policy>::accept(
		socket_rhs &sock) const
{
	if(_sock == SOCKET_ERROR) {
		error_policy::msg("Error in socket::accept: _sock == -1");
	}
	locking_policy::lock();

	int addr_len = sizeof(_serv);
	sock._sock = ::accept(_sock, (SOCKADDR*)&_serv, 
			(int*) &addr_len);

	locking_policy::unlock();

	if(sock._sock == SOCKET_ERROR) {
		error_policy::msg("Error in socket::accept: sock._sock <= 0");
		return false;
	}
	return true;
}

